package com.yjkf.zh.admin.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.*;

public class JwtTokenUtils implements Serializable {

    private static final long serialVersionUID = 1L;

    //用户名称
    private static final String USERNAME = Claims.SUBJECT;
    //创建时间
    private static final String CREATED = "created";
    //权限列表
    private static final String AUTHORITIES = "authorities";
    //密钥
    private static final String SECRET = "abcdefgh";
    //有效时长12小时
    private static final long EXPIRE_TIME = 12 * 60 * 60 * 1000;

    public static Authentication getAuthenticationeFromToken(HttpServletRequest request) {
        Authentication authentication = null;
        //获取请求携带的令牌
        String token = JwtTokenUtils.getToken(request);
        if (token != null) {
            if (SecurityUtils.getAuthentication() == null) {
                Claims claims = getClaimsFromToken(token);
                if(claims == null){
                    return null;
                }
                String username = claims.getSubject();
                if(username == null){
                    return null;
                }
                if(isTokenExpired(token)){      //判断token是否过期
                    return null;
                }
                Object authors = claims.get(AUTHORITIES);
                List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
                if(authors != null && authors instanceof  List){
                    for(Object object : (List)authors){
                        authorities.add(new GrantedAuthorityImpl(
                                (String)((Map)object).get("authority")
                        ));
                    }
                }
                authentication = new JwtAuthenticationToken(username,null,authorities,token);
            }else {
                if(validateToken(token,SecurityUtils.getUsername())){
                    authentication = SecurityUtils.getAuthentication();
                }
            }
        }
        return authentication;
    }

    public static String getToken(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        String tokenHead = "Bearer";
        if (token == null) {
            token = request.getHeader("token");
        } else if (token.contains(tokenHead)) {
            token = token.substring(tokenHead.length());
        }
        if ("".equals(token)) {
            token = null;
        }
        return token;
    }


    private static Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        }catch (Exception e){
            claims = null;
        }
        return claims;
    }

    //判断令牌是否过期
    public static Boolean isTokenExpired(String token){
        try {
            Claims claims = getClaimsFromToken(token);
            Date exiration = claims.getExpiration();
            return exiration.before(new Date());
        }catch (Exception e){
            return false;
        }
    }

    //验证令牌
    public static Boolean validateToken(String token,String username){
        String userName = getUsernameFromToken(token);
        return (userName.equals(username) && !isTokenExpired(token));
    }

    //从令牌中获取用户名
    public static String getUsernameFromToken(String token){
        String username;
        try {
            Claims claims = getClaimsFromToken(token);
            username = claims.getSubject();
        }catch (Exception e){
            username = null;
        }
        return username;
    }

    //生成令牌
    public static String generateToken(Authentication authentication){
        Map<String,Object> claims = new HashMap<>(3);
        claims.put(USERNAME, SecurityUtils.getUsername(authentication));
        claims.put(CREATED,new Date());
        claims.put(AUTHORITIES,authentication.getAuthorities());
        return generateToken(claims);
    }

    private static String generateToken(Map<String, Object> claims){
        Date expirationDate = new Date(System.currentTimeMillis()+EXPIRE_TIME);
        return Jwts.builder().setClaims(claims).setExpiration(expirationDate)
                .signWith(SignatureAlgorithm.HS512,SECRET).compact();
    }

    public static void main(String[] args){
        Date expirationDate = new Date(System.currentTimeMillis()+EXPIRE_TIME);
        System.out.println(new Date(
        ));
        System.out.println(expirationDate);
    }
}
